prepare-root: create /run/systemd/volatile-root for composefs
systemd resolves the block device backing the root filesystem via
blockdev_get_root(), which checks "/" and falls back to "/usr". With
composefs enabled both are overlayfs mounts with an anonymous st_dev
(and prepare-root intentionally skips the read-only /usr bind mount in
that case), so the lookup finds no device. As a result
systemd-gpt-auto-generator silently skips all partition discovery: the
ESP is never automounted on /boot, which in turn breaks tools that
expect the bootfs to be reachable, e.g. bootctl, systemd-bless-boot
(boot counting) and "ostree admin status" when the loader entries live
on the ESP.
systemd provides a hook for exactly this situation: if the root mount
has been replaced by some form of volatile file system, the original
root block device is expected to be symlinked at
/run/systemd/volatile-root. Create that symlink when composefs is in
use. Note the target must be in the /dev/block/MAJ:MIN form since
systemd parses it without ever going to disk
(device_path_parse_major_minor()).
The root device is resolved as follows: prefer /dev/gpt-auto-root when
it exists, since on systemd-based initrds udev has already identified
the root partition for us (EFI boot with LoaderDevicePartUUID set and
a discoverable-partitions-spec root partition type). Otherwise fall
back to stat()ing the root mountpoint, which also covers initrds
without systemd (e.g. meta-updater). Since btrfs reports an anonymous
st_dev (major 0) for its mounts, in that case query the backing device
via BTRFS_IOC_FS_INFO/BTRFS_IOC_DEV_INFO the same way systemd's
btrfs_get_block_device_fd() does, refusing multi-device filesystems
just as systemd does. This matters in practice as Fedora Atomic
Desktops default to composefs on btrfs.
bootc solves the same problem the same way for its composefs-native
backend: bootc-root-setup.service (gated on the composefs= karg) runs a
gpt_workaround() that creates this exact symlink. That service is
ordered after ostree-prepare-root.service, so with this change the
symlink already exists by the time it runs; bootc is being updated to
tolerate that instead of failing. See also the systemd discussion of
gpt-auto with overlay roots:
https://github.com/systemd/systemd/issues/35017
Failure to create the symlink is not fatal: the system boots fine
without it, only auto-discovery of auxiliary partitions is degraded.